// api_metric.go
package controllers

import (
	"context"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"math"
	"net/http"

	"sort"
	"strconv"
	"strings"
	"time"

	"xwaf_admin/common"

	"xwaf_admin/ip2regionv2"

	"github.com/tidwall/gjson"

	beego "github.com/beego/beego/v2/server/web"
	"github.com/olivere/elastic/v7"
)

type MetricController struct {
	beego.Controller
}

type DistMain struct {
	XName    []string     `json:"xname"`
	Subvalue []CountItemh `json:"subvalue"`
}

// 用于对合计结果进行排序的数据结构
type CountItemh struct {
	Name  string `json:"name"`
	Value int64  `json:"value"`
}

// 用于对合计结果进行排序包含百分比
type CountItemh2 struct {
	Name    string `json:"name"`
	Percent string `json:"percent"`
	Value   int64  `json:"value"`
}

// 排序数据结构
type ByCounth []CountItemh

func (c ByCounth) Len() int           { return len(c) }
func (c ByCounth) Swap(i, j int)      { c[i], c[j] = c[j], c[i] }
func (c ByCounth) Less(i, j int) bool { return c[i].Value > c[j].Value }

// 排序并打印合计的数据项字典
func PrintMapjson(m map[string]int64, base int64, top int, islist bool) string {
	var bc ByCounth = make([]CountItemh, 0, len(m))
	var bbc = make([]CountItemh, 0, len(m))
	var bbc2 = make([]CountItemh2, 0, len(m))
	var dname []string

	for k, v := range m {
		bc = append(bc, *&CountItemh{k, v})
	}

	sort.Sort(bc)

	for i, v := range bc {
		if islist {
			xpercet := fmt.Sprintf("%.3f", float64(v.Value)/float64(base)*100)
			bbc2 = append(bbc2, *&CountItemh2{v.Name, xpercet, v.Value})
		} else {
			dname = append(dname, v.Name)
			bbc = append(bbc, *&CountItemh{v.Name, v.Value})
		}
		if i > top {
			break
		}
	}

	if islist {
		jsonStr, err := json.Marshal(bbc2)
		if err != nil {
			fmt.Println(err)
		}
		return fmt.Sprintf("%s", jsonStr)
	} else {
		aaa := &DistMain{
			XName:    dname,
			Subvalue: bbc,
		}
		jsonStr, err := json.Marshal(aaa)
		if err != nil {
			fmt.Println(err)
		}
		return fmt.Sprintf("%s", jsonStr)
	}
}

type Jsmain struct {
	Dtime []string  `json:"dtime"`
	Data  []float64 `json:"data"`
}

//line 排序
type LineItem struct {
	Name  int64   `json:"name"`
	Value float64 `json:"value"`
}
type LineArry []LineItem

func (c LineArry) Len() int           { return len(c) }
func (c LineArry) Swap(i, j int)      { c[i], c[j] = c[j], c[i] }
func (c LineArry) Less(i, j int) bool { return c[i].Name > c[j].Name }

//用于处理状态码和时间的分布的图表
type DistCt struct {
	XName    []string   `json:"xname"`
	Subvalue []DistItem `json:"subvalue"`
}

type DistItem struct {
	Name  string `json:"name"`
	Value int64  `json:"value"`
}

//多条曲线ip，及去重ip的曲线
type LineMain struct {
	Dtime     []string `json:"dtime"`
	Title     []string `json:"title"`
	Livevalue []Lvalue `json:"subvalue"`
}
type Lvalue struct {
	Name  string  `json:"name"`
	Type  string  `json:"type"`
	Stack string  `json:"stack"`
	Data  []int64 `json:"data"`
}

func AttackTypeConvert(atstr string) string {
	switch atstr {
	case "WHITE_IP":
		return "IP白名单"
	case "BAD_IP":
		return "封禁IP"
	case "RISK_IP":
		return "威胁IP"
	case "BLACK_IP":
		return "IP黑名单"
	case "WHITE_URL":
		return "URL白名单"
	case "WHITE_UA":
		return "UA白名单"
	case "DENY_COOKIE":
		return "CSRF攻击"
	case "DENY_URI":
		return "URL扫描"
	case "DENY_ARGS":
		return "参数注入"
	case "DENY_UA":
		return "UA扫描器"
	case "DENY_POSTDATAS":
		return "POST注入"
	case "URL_TooLong":
		return "URL长度限制"
	case "IPURI_LIMIT":
		return "IpUrl限流"
	case "IP_LIMIT":
		return "单IP限流"
	case "UA_LIMIT":
		return "UA限流"
	case "RF_LIMIT":
		return "Reffer限流"
	case "CIP_LIMIT":
		return "C段IP限流"
	case "ALL_LIMIT":
		return "总Qps限流"
	case "RISK_IP_LIMIT":
		return "威胁IP限流"
	case "URL_IP_LIMIT":
		return "自定义URL,IP限流"
	case "URL_CIP_LIMIT":
		return "自定义URL,C段IP限流"
	case "URL_RF_LIMIT":
		return "自定义URL,reffer限流"
	case "URL_ARGS_LIMIT":
		return "自定义URL,args限流"
	case "URL_UA_LIMIT":
		return "自定义URL,UA限流"
	case "URL_ALL_LIMIT":
		return "自定义URL,总Qps"
	default:
		return atstr
	}
}

//get /metric/v1/line  单一曲线图
func (this *MetricController) V1Line() {
	//r.ParseForm()
	//var appName, attackType, logType, serverName, clientIp, sTime, eTime string

	appName := this.GetString("appname")
	attackType := this.GetString("attackType")
	logType := this.GetString("logType")
	serverName := this.GetString("serverName")
	clientIp := this.GetString("clientIp")
	startTime := this.GetString("starttime")
	endTime := this.GetString("endtime")

	//nowTime := time.Now().UnixNano() / 1e6
	if endTime == "" {
		endTime = time.Now().Format("2006-01-02T15:04:05")
	}
	if startTime == "" {
		startTime = time.Now().Add(-1 * time.Hour).Format("2006-01-02T15:04:05")
	}

	log.Printf("st:%s,et:%s", startTime, endTime)

	appNameArry := strings.Split(appName, ",")
	appNameCals := make([]interface{}, len(appNameArry))

	attackTypeArry := strings.Split(attackType, ",")
	attackTypeCals := make([]interface{}, len(attackTypeArry))

	logTypeArry := strings.Split(logType, ",")
	logTypeCals := make([]interface{}, len(logTypeArry))

	serverNameArry := strings.Split(serverName, ",")
	serverNameCals := make([]interface{}, len(serverNameArry))

	clientIpArry := strings.Split(clientIp, ",")
	clientIpCals := make([]interface{}, len(clientIpArry))

	query := elastic.NewBoolQuery()
	query = query.Must(elastic.NewRangeQuery("hTime").Gte(startTime).Lte(endTime))

	if appName != "" {
		for i, v := range strings.Split(appName, ",") {
			appNameCals[i] = v
		}
		query = query.Must(elastic.NewTermsQuery("appName.keyword", appNameCals...))
	}

	if attackType != "" {
		for i, v := range strings.Split(attackType, ",") {
			attackTypeCals[i] = v
		}
		query = query.Must(elastic.NewTermsQuery("attackType.keyword", attackTypeCals...))
	}

	if logType != "" {
		for i, v := range strings.Split(logType, ",") {
			logTypeCals[i] = v
		}
		query = query.Must(elastic.NewTermsQuery("logType.keyword", logTypeCals...))
	}

	if serverName != "" {
		for i, v := range strings.Split(serverName, ",") {
			serverNameCals[i] = v
		}
		query = query.Must(elastic.NewTermsQuery("serverName.keyword", serverNameCals...))
	}
	if clientIp != "" {
		for i, v := range strings.Split(clientIp, ",") {
			clientIpCals[i] = v
		}
		query = query.Must(elastic.NewTermsQuery("clientIp.keyword", clientIpCals...))
	}

	loc, _ := time.LoadLocation("Local") //重要：获取时区
	tmsT, _ := time.ParseInLocation("2006-01-02T15:04:05", startTime, loc)
	tmeT, _ := time.ParseInLocation("2006-01-02T15:04:05", endTime, loc)

	sTmp := tmsT.Unix() * 1000
	eTmp := tmeT.Unix() * 1000
	//log.Printf("st:%d,et:%d", sTmp, eTmp)
	indexstr := common.GetIndex("xwaf", sTmp, eTmp)

	tone := (eTmp - sTmp) / 1000
	var intv, dfmat string
	switch {
	case tone < 4*60*60:
		intv = "5m"
		dfmat = "HH:mm"
		//	case tone < 8*60*60:
		//		intv = "10m"
		//		dfmat = "HH:mm"
		//	case tone < 25*60*60:
		//		intv = "30m"
		//		dfmat = "HH:mm"
	case tone < 73*60*60:
		intv = "hour"
		dfmat = "dd/HH"
		//	case tone < 169*60*60:
		//		intv = "2h"
		//		dfmat = "dd/HH"
	case tone < 60*24*60*60:
		intv = "day"
		dfmat = "MM-dd"
	default:
		intv = "month"
		dfmat = "yy-MM"
	}
	//log.Printf("interva:%s,format:%s\n", intv, dfmat)

	//调试查询后的语法
	// src, err := query.Source()
	// if err != nil {
	// 	panic(err)
	// }
	// data, err := json.MarshalIndent(src, "", "  ")
	// if err != nil {
	// 	panic(err)
	// }
	// fmt.Println(string(data))

	queryResult := common.Esclient.Search().Index(indexstr...).Query(query).Size(0)
	esearch := queryResult.Aggregation("Allcount", elastic.NewDateHistogramAggregation().Field("hTime").Interval(intv).Format(dfmat))

	ctx := context.Background()
	eresult, err1 := esearch.Do(ctx)
	if err1 != nil {
		panic(err1)
	}

	//var aggMap = make(map[string]int64)
	//totalhit := eresult.Hits.TotalHits

	var timeStamp = make([]string, 0)
	var allCnt = make([]int64, 0)

	if agg, found := eresult.Aggregations.Terms("Allcount"); found {
		for _, bucket := range agg.Buckets {
			timeStamp = append(timeStamp, *bucket.KeyAsString)
			allCnt = append(allCnt, bucket.DocCount)
		}
	}
	var bbb = make([]Lvalue, 0)
	bbb = append(bbb, *&Lvalue{"waf", "line", "waf", allCnt})

	aaa := &LineMain{
		Dtime:     timeStamp,
		Livevalue: bbb,
	}

	this.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Origin", "*")
	this.Ctx.ResponseWriter.Header().Set("Content-Type", "application/json;charset=utf-8")

	jsonStr, jerr := json.Marshal(aaa)
	if jerr != nil {
		log.Println("ERROR: aggMap json.Marshal error")
		//panic(jerr)
	}
	this.Ctx.WriteString(string(jsonStr))
}

//
//get /metric/v3/line  多分组曲线图
func (this *MetricController) V3Line() {
	//r.ParseForm()
	appName := this.GetString("appname")
	attackType := this.GetString("attackType")
	logType := this.GetString("logType")
	serverName := this.GetString("serverName")
	clientIp := this.GetString("clientIp")
	startTime := this.GetString("starttime")
	endTime := this.GetString("endtime")

	field := this.GetString("field") //日志字段
	if field == "" {
		field = "logType"
	}

	dfmat := this.GetString("dfmat")
	intv := this.GetString("intv")
	etype := this.GetString("etype") //echart 的图表类型，是选择柱形[bar],stack类型为total才是柱形，还是曲线[line]
	stack := this.GetString("stack") //echart 的图表类型，是选择柱形[bar],stack类型为total才是堆叠柱形[多个name的数字堆叠到一个柱子],否则为每个name一个柱子。

	if etype == "" {
		etype = "line"
	}

	//nowTime := time.Now().UnixNano() / 1e6
	if endTime == "" {
		endTime = time.Now().Format("2006-01-02T15:04:05")
	}
	if startTime == "" {
		startTime = time.Now().Add(-1 * time.Hour).Format("2006-01-02T15:04:05")
	}

	appNameArry := strings.Split(appName, ",")
	appNameCals := make([]interface{}, len(appNameArry))

	attackTypeArry := strings.Split(attackType, ",")
	attackTypeCals := make([]interface{}, len(attackTypeArry))

	logTypeArry := strings.Split(logType, ",")
	logTypeCals := make([]interface{}, len(logTypeArry))

	serverNameArry := strings.Split(serverName, ",")
	serverNameCals := make([]interface{}, len(serverNameArry))

	clientIpArry := strings.Split(clientIp, ",")
	clientIpCals := make([]interface{}, len(clientIpArry))

	query := elastic.NewBoolQuery()
	query = query.Must(elastic.NewRangeQuery("hTime").Gte(startTime).Lte(endTime))
	var titleArry = make([]string, 0)
	if appName != "" {
		for i, v := range strings.Split(appName, ",") {
			appNameCals[i] = v
		}
		query = query.Must(elastic.NewTermsQuery("appName.keyword", appNameCals...))
	}

	if attackType != "" {
		for i, v := range strings.Split(attackType, ",") {
			attackTypeCals[i] = v
		}
		query = query.Must(elastic.NewTermsQuery("attackType.keyword", attackTypeCals...))
	}

	if logType != "" {
		titleArry = strings.Split(logType, ",")
		for i, v := range strings.Split(logType, ",") {
			logTypeCals[i] = v
		}
		query = query.Must(elastic.NewTermsQuery("logType.keyword", logTypeCals...))
	}

	if serverName != "" {
		for i, v := range strings.Split(serverName, ",") {
			serverNameCals[i] = v
		}
		query = query.Must(elastic.NewTermsQuery("serverName.keyword", serverNameCals...))
	}
	if clientIp != "" {
		for i, v := range strings.Split(clientIp, ",") {
			clientIpCals[i] = v
		}
		query = query.Must(elastic.NewTermsQuery("clientIp.keyword", clientIpCals...))
	}

	loc, _ := time.LoadLocation("Local") //重要：获取时区
	tmsT, _ := time.ParseInLocation("2006-01-02T15:04:05", startTime, loc)
	tmeT, _ := time.ParseInLocation("2006-01-02T15:04:05", endTime, loc)

	sTmp := tmsT.Unix() * 1000
	eTmp := tmeT.Unix() * 1000
	//log.Printf("st:%d,et:%d", sTmp, eTmp)
	indexstr := common.GetIndex("xwaf", sTmp, eTmp)

	//fmt.Println(indexstr)
	//var intv, dfmat string
	if intv == "" && dfmat == "" {
		tone := (eTmp - sTmp) / 1000
		switch {
		case tone < 2*60*60:
			intv = "1m"
			dfmat = "HH:mm"
		case tone < 4*60*60:
			intv = "5m"
			dfmat = "HH:mm"
		case tone < 73*60*60:
			intv = "hour"
			dfmat = "dd/HH"
		case tone < 60*24*60*60:
			intv = "day"
			dfmat = "MM-dd"
		default:
			intv = "month"
			dfmat = "yy-MM"
		}
	}
	//log.Printf("interva:%s,format:%s\n", intv, dfmat)
	queryResult := common.Esclient.Search().Index(indexstr...).Query(query).Size(0)
	esearch := queryResult.Aggregation("allCount", elastic.NewDateHistogramAggregation().Field("hTime").Interval(intv).Format(dfmat).
		SubAggregation("logtypeCount", elastic.NewTermsAggregation().Field(field+".keyword").Size(50)))

	ctx := context.Background()
	eresult, err1 := esearch.Do(ctx)
	if err1 != nil {
		panic(err1)
	}

	//var aggMap = make(map[string]int64)
	//totalhit := eresult.Hits.TotalHits

	var timeStamp = make([]string, 0)
	var titleMap = make(map[string]int)
	var tmslength int64

	var agg *elastic.AggregationBucketKeyItems
	var found bool

	agg, found = eresult.Aggregations.Terms("allCount")
	if found {
		for _, bucket := range agg.Buckets {
			tmslength++
			timeStamp = append(timeStamp, *bucket.KeyAsString)
			if logType == "" {
				if tag, found1 := bucket.Terms("logtypeCount"); found1 {
					for _, dv := range tag.Buckets {
						if dv.Key.(string) != "" {
							var tt = dv.Key.(string)
							if tt == "waf" {
								tt = "入侵防护"
							}
							if tt == "reqlimit" {
								tt = "防刷限流"
							}
							if tt == "bwlist" {
								tt = "黑白名单"
							}
							titleMap[tt] = 1
						}
					}
				}
			}
		}
	} else {
		this.Ctx.WriteString("err:not found")
	}

	//初始化map后的数组
	var TmpMapArry = make(map[string][]int64)
	if logType == "" {
		for kk, _ := range titleMap {
			titleArry = append(titleArry, kk)
			TmpMapArry[kk] = make([]int64, tmslength)
		}
	} else {
		for _, vv := range titleArry {
			TmpMapArry[vv] = make([]int64, tmslength)
		}
	}

	if found {
		for ii, bucket := range agg.Buckets {
			if tag, found1 := bucket.Terms("logtypeCount"); found1 {
				for _, dv := range tag.Buckets {
					if dv.Key.(string) != "" {
						//fmt.Printf("%s %d %d\n", dv.Key.(string), ii, dv.DocCount)
						var tt = dv.Key.(string)
						if tt == "waf" {
							tt = "入侵防护"
						}
						if tt == "reqlimit" {
							tt = "防刷限流"
						}
						if tt == "bwlist" {
							tt = "黑白名单"
						}
						TmpMapArry[tt][ii] = dv.DocCount
						//uqvalue, _ := dv.Aggregations.Cardinality("groupuniqip")
						//TmpMapArry[dv.Key.(string)][ii] = int64(*uqvalue.Value)
						//fmt.Printf("%s %d %f\n", dv.Key.(string), ii, *uqvalue.Value)
					}
				}
			}
		}
	}

	var bbb = make([]Lvalue, 0)
	var stackstr = stack
	for kk, vv := range TmpMapArry {
		if stack == "" {
			stackstr = kk
		}
		bbb = append(bbb, *&Lvalue{kk, etype, stackstr, vv}) //etype为bar[柱形]还是line[曲线],stack为total时为堆叠柱子，否则为独立的柱子
	}

	aaa := &LineMain{
		Dtime:     timeStamp,
		Title:     titleArry,
		Livevalue: bbb,
	}

	this.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Origin", "*")
	this.Ctx.ResponseWriter.Header().Set("Content-Type", "application/json;charset=utf-8")

	jsonStr, jerr := json.Marshal(aaa)
	if jerr != nil {
		log.Println("ERROR: aggMap json.Marshal error")
		//panic(jerr)
	}
	this.Ctx.WriteString(string(jsonStr))
}

type MetricDistMain struct {
	Code  int64            `json:"code"`
	Name  []string         `json:"name"`
	Msg   string           `json:"msg"`
	Count int64            `json:"count"`
	Data  []MetricDistItem `json:"data"`
}

type MetricDistItem struct {
	Name    string  `json:"name"`
	Value   float64 `json:"value"`
	Ratio   float64 `json:"ratio"`
	Remarks string  `json:"remarks"`
}

//饼图
//get /metric/v2/dist
func (this *MetricController) V2Dist() {
	//r.ParseForm()
	appName := this.GetString("appname")
	attackType := this.GetString("attackType")
	logType := this.GetString("logType")
	serverName := this.GetString("serverName")
	clientIp := this.GetString("clientIp")
	startTime := this.GetString("starttime")
	endTime := this.GetString("endtime")
	area := this.GetString("area")
	searchtype := this.GetString("key")

	//nowTime := time.Now().UnixNano() / 1e6
	if endTime == "" {
		endTime = time.Now().Format("2006-01-02T15:04:05")
	}
	if startTime == "" {
		startTime = time.Now().Add(-1 * time.Hour).Format("2006-01-02T15:04:05")
	}
	if searchtype == "" {
		this.Ctx.WriteString("Key cannot be empty")
		return
	}

	tsize := this.GetString("size")
	var err error
	var totalsize int
	if tsize == "" {
		totalsize = 50
	} else {
		totalsize, err = strconv.Atoi(tsize)
		if err != nil {
			log.Println("ERROR: size strconv.Atoi error")
			panic(err)
		}
	}
	appNameArry := strings.Split(appName, ",")
	appNameCals := make([]interface{}, len(appNameArry))

	attackTypeArry := strings.Split(attackType, ",")
	attackTypeCals := make([]interface{}, len(attackTypeArry))

	logTypeArry := strings.Split(logType, ",")
	logTypeCals := make([]interface{}, len(logTypeArry))

	serverNameArry := strings.Split(serverName, ",")
	serverNameCals := make([]interface{}, len(serverNameArry))

	clientIpArry := strings.Split(clientIp, ",")
	clientIpCals := make([]interface{}, len(clientIpArry))

	query := elastic.NewBoolQuery()
	query = query.Must(elastic.NewRangeQuery("hTime").Gte(startTime).Lte(endTime))
	//var titleArry = make([]string, 0)

	if appName != "" {
		for i, v := range strings.Split(appName, ",") {
			appNameCals[i] = v
		}
		query = query.Must(elastic.NewTermsQuery("appName.keyword", appNameCals...))
	}

	if attackType != "" {
		for i, v := range strings.Split(attackType, ",") {
			attackTypeCals[i] = v
		}
		query = query.Must(elastic.NewTermsQuery("attackType.keyword", attackTypeCals...))
	}

	if logType != "" {
		for i, v := range strings.Split(logType, ",") {
			logTypeCals[i] = v
		}
		query = query.Must(elastic.NewTermsQuery("logType.keyword", logTypeCals...))
	}

	if serverName != "" {
		for i, v := range strings.Split(serverName, ",") {
			serverNameCals[i] = v
		}
		query = query.Must(elastic.NewTermsQuery("serverName.keyword", serverNameCals...))
	}
	if clientIp != "" {
		for i, v := range strings.Split(clientIp, ",") {
			clientIpCals[i] = v
		}
		query = query.Must(elastic.NewTermsQuery("clientIp.keyword", clientIpCals...))
	}

	loc, _ := time.LoadLocation("Local") //重要：获取时区
	tmsT, _ := time.ParseInLocation("2006-01-02T15:04:05", startTime, loc)
	tmeT, _ := time.ParseInLocation("2006-01-02T15:04:05", endTime, loc)

	sTmp := tmsT.Unix() * 1000
	eTmp := tmeT.Unix() * 1000
	//log.Printf("st:%d,et:%d", sTmp, eTmp)
	indexstr := common.GetIndex("xwaf", sTmp, eTmp)

	//queryResult := common.EsclientSearch().Index(indexstr...).Query(query).TrackTotalHits(true).Size(0)
	queryResult := common.Esclient.Search().Index(indexstr...).Query(query).Size(0)

	var esearch *elastic.SearchService
	switch searchtype {
	case "attackType":
		esearch = queryResult.Aggregation(searchtype, elastic.NewTermsAggregation().Field("attackType.keyword").Size(totalsize))
	case "appName":
		esearch = queryResult.Aggregation(searchtype, elastic.NewTermsAggregation().Field("appName.keyword").Size(totalsize))
	case "serverName":
		esearch = queryResult.Aggregation(searchtype, elastic.NewTermsAggregation().Field("serverName.keyword").Size(totalsize))
	case "clientIp":
		esearch = queryResult.Aggregation(searchtype, elastic.NewTermsAggregation().Field("clientIp.keyword").Size(totalsize))
	case "reqUrl":
		esearch = queryResult.Aggregation(searchtype, elastic.NewTermsAggregation().Field("reqUrl.keyword").Size(totalsize))
	case "userAgent":
		esearch = queryResult.Aggregation(searchtype, elastic.NewTermsAggregation().Field("userAgent.keyword").Size(totalsize))
	}

	ctx := context.Background()
	eresult, err1 := esearch.Do(ctx)
	if err1 != nil {
		log.Println("ERROR: esearch.Do error")
		panic(err1)
	}

	totalhit := eresult.Hits.TotalHits.Value
	//log.Println(totalhit)
	//var uniqipcount int64
	//var iprect *IpCountRct2

	//var aggMap = make(map[string]int64)

	var DistArry = make([]MetricDistItem, 0)
	var NameArry = []string{}
	var count int64
	if agg, found := eresult.Aggregations.Terms(searchtype); found {
		//othercount := agg.SumOfOtherDocCount
		count = int64(len(agg.Buckets))
		for _, bucket := range agg.Buckets {
			//fmt.Printf("key:%s,value:%d\n", bucket.Key.(string), bucket.DocCount)
			//aggMap[bucket.Key.(string)] = bucket.DocCount
			ratiovalue := float64(bucket.DocCount) / float64(totalhit)
			titles := bucket.Key.(string)
			if searchtype == "attackType" {
				titles = AttackTypeConvert(bucket.Key.(string))
			}
			var rmks string
			if searchtype == "clientIp" {
				if area == "region" {
					rmks = strings.Trim(ip2regionv2.IpToRegion(bucket.Key.(string)), "省")
				} else {
					rmks = ip2regionv2.IpToCity(bucket.Key.(string))
				}
			}
			Items := &MetricDistItem{
				Name:    titles,
				Value:   float64(bucket.DocCount),
				Ratio:   math.Trunc((ratiovalue+0.5/math.Pow10(3))*math.Pow10(3)) / math.Pow10(3),
				Remarks: rmks,
			}
			DistArry = append(DistArry, *Items)
			NameArry = append(NameArry, bucket.Key.(string))
		}
		//aggMap["other"] = othercount
	}

	sMain := &MetricDistMain{
		Code:  0,
		Name:  NameArry,
		Msg:   "",
		Count: count,
		Data:  DistArry,
	}

	this.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Origin", "*")
	this.Ctx.ResponseWriter.Header().Set("Content-Type", "application/json;charset=utf-8")

	jsonStr, jerr := json.Marshal(sMain)
	if jerr != nil {
		log.Println("ERROR: simpledetail json.Marshal error")
		//panic(jerr)
	}
	this.Ctx.WriteString(string(jsonStr))

	//log.Println(iprect)
	//fmt.Fprintf(w, PrintMapjson(aggMap, totalhit, 50, true))
}

//柱状图
////get /metric/v1/bar  告警根据不同的key来显示不同的柱状图
func (this *MetricController) V1Bar() {
	//r.ParseForm()

	appName := this.GetString("appname")
	attackType := this.GetString("attackType")
	logType := this.GetString("logType")
	serverName := this.GetString("serverName")
	clientIp := this.GetString("clientIp")
	startTime := this.GetString("starttime")
	endTime := this.GetString("endtime")
	searchtype := this.GetString("key")

	//nowTime := time.Now().UnixNano() / 1e6
	if endTime == "" {
		endTime = time.Now().Format("2006-01-02T15:04:05")
	}
	if startTime == "" {
		startTime = time.Now().Add(-1 * time.Hour).Format("2006-01-02T15:04:05")
	}

	if searchtype == "" {
		this.Ctx.WriteString("Key cannot be empty")
		return
	}

	appNameArry := strings.Split(appName, ",")
	appNameCals := make([]interface{}, len(appNameArry))

	attackTypeArry := strings.Split(attackType, ",")
	attackTypeCals := make([]interface{}, len(attackTypeArry))

	logTypeArry := strings.Split(logType, ",")
	logTypeCals := make([]interface{}, len(logTypeArry))

	serverNameArry := strings.Split(serverName, ",")
	serverNameCals := make([]interface{}, len(serverNameArry))

	clientIpArry := strings.Split(clientIp, ",")
	clientIpCals := make([]interface{}, len(clientIpArry))

	query := elastic.NewBoolQuery()
	query = query.Must(elastic.NewRangeQuery("hTime").Gte(startTime).Lte(endTime))
	//var titleArry = make([]string, 0)

	if appName != "" {
		for i, v := range strings.Split(appName, ",") {
			appNameCals[i] = v
		}
		query = query.Must(elastic.NewTermsQuery("appName.keyword", appNameCals...))
	}

	if attackType != "" {
		for i, v := range strings.Split(attackType, ",") {
			attackTypeCals[i] = v
		}
		query = query.Must(elastic.NewTermsQuery("attackType.keyword", attackTypeCals...))
	}

	if logType != "" {
		for i, v := range strings.Split(logType, ",") {
			logTypeCals[i] = v
		}
		query = query.Must(elastic.NewTermsQuery("logType.keyword", logTypeCals...))
	}

	if serverName != "" {
		for i, v := range strings.Split(serverName, ",") {
			serverNameCals[i] = v
		}
		query = query.Must(elastic.NewTermsQuery("serverName.keyword", serverNameCals...))
	}
	if clientIp != "" {
		for i, v := range strings.Split(clientIp, ",") {
			clientIpCals[i] = v
		}
		query = query.Must(elastic.NewTermsQuery("clientIp.keyword", clientIpCals...))
	}

	loc, _ := time.LoadLocation("Local") //重要：获取时区
	tmsT, _ := time.ParseInLocation("2006-01-02T15:04:05", startTime, loc)
	tmeT, _ := time.ParseInLocation("2006-01-02T15:04:05", endTime, loc)

	sTmp := tmsT.Unix() * 1000
	eTmp := tmeT.Unix() * 1000
	//log.Printf("st:%d,et:%d", sTmp, eTmp)
	indexstr := common.GetIndex("xwaf", sTmp, eTmp)

	tone := (eTmp - sTmp) / 1000
	var intv, dfmat string
	switch {
	case tone < 4*60*60:
		intv = "5m"
		dfmat = "HH:mm"
	case tone < 73*60*60:
		intv = "hour"
		dfmat = "dd/HH"
	case tone < 60*24*60*60:
		intv = "day"
		dfmat = "MM-dd"
	default:
		intv = "month"
		dfmat = "yy-MM"
	}
	//log.Printf("interva:%s,format:%s\n", intv, dfmat)
	queryResult := common.Esclient.Search().Index(indexstr...).Query(query).Size(0)
	esearch := queryResult.Aggregation("warncount", elastic.NewDateHistogramAggregation().Field("hTime").Interval(intv).Format(dfmat).TimeZone("+08:00").
		SubAggregation(searchtype, elastic.NewTermsAggregation().Field(searchtype+".keyword").Size(50)))

	ctx := context.Background()
	eresult, err1 := esearch.Do(ctx)
	if err1 != nil {
		panic(err1)
	}

	//var aggMap = make(map[string]int64)
	//totalhit := eresult.Hits.TotalHits

	var timeStamp = make([]string, 0)
	var titleMap = make(map[string]int)
	var tmslength int64

	var agg *elastic.AggregationBucketKeyItems
	var found bool

	agg, found = eresult.Aggregations.Terms("warncount")
	if found {
		for _, bucket := range agg.Buckets {
			tmslength++
			timeStamp = append(timeStamp, *bucket.KeyAsString)
			if tag, found1 := bucket.Terms(searchtype); found1 {
				for _, dv := range tag.Buckets {
					if dv.Key.(string) != "" {
						titleMap[dv.Key.(string)] = 1
					}
				}
			}
		}
	} else {
		this.Ctx.WriteString("err:not found")
		return
	}

	var titleArry = make([]string, 0)
	//初始化map后的数组
	var TmpMapArry = make(map[string][]int64)
	for kk, _ := range titleMap {
		titleArry = append(titleArry, kk)
		TmpMapArry[kk] = make([]int64, tmslength)
	}

	if found {
		for ii, bucket := range agg.Buckets {
			if tag, found1 := bucket.Terms(searchtype); found1 {
				for _, dv := range tag.Buckets {
					if dv.Key.(string) != "" {
						TmpMapArry[dv.Key.(string)][ii] = dv.DocCount
						//fmt.Printf("%s %d %d\n", dv.Key.(string), ii, dv.DocCount)
					}
				}
			}
		}
	}

	var bbb = make([]Lvalue, 0)
	for kk, vv := range TmpMapArry {
		bbb = append(bbb, *&Lvalue{kk, "bar", "total", vv})
	}

	aaa := &LineMain{
		Dtime:     timeStamp,
		Title:     titleArry,
		Livevalue: bbb,
	}
	this.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Origin", "*")
	this.Ctx.ResponseWriter.Header().Set("Content-Type", "application/json;charset=utf-8")

	jsonStr, jerr := json.Marshal(aaa)
	if jerr != nil {
		log.Println("ERROR: aggMap json.Marshal error")
		//panic(jerr)
	}
	this.Ctx.WriteString(string(jsonStr))
}

//
type BarV2Main struct {
	Code     int64       `json:"code"`
	Title    []string    `json:"title"`
	Name     []string    `json:"name"`
	Subvalue []BarV2Item `json:"subvalue"`
}

type BarV2Item struct {
	Name  string  `json:"name"`
	Type  string  `json:"type"`
	Stack string  `json:"stack"`
	Data  []int64 `json:"data"`
}

//柱状图
////从域名维度显示一段时间内waf和reqlimit的数量
func (this *MetricController) V2Bar() {
	//r.ParseForm()

	appName := this.GetString("appname")
	attackType := this.GetString("attackType")
	logType := this.GetString("logType")
	serverName := this.GetString("serverName")
	clientIp := this.GetString("clientIp")
	startTime := this.GetString("starttime")
	endTime := this.GetString("endtime")
	searchtype := this.GetString("key")

	//nowTime := time.Now().UnixNano() / 1e6
	if endTime == "" {
		endTime = time.Now().Format("2006-01-02T15:04:05")
	}
	if startTime == "" {
		startTime = time.Now().Add(-1 * time.Hour).Format("2006-01-02T15:04:05")
	}

	if searchtype == "" {
		this.Ctx.WriteString("Key cannot be empty")
		return
	}

	appNameArry := strings.Split(appName, ",")
	appNameCals := make([]interface{}, len(appNameArry))

	attackTypeArry := strings.Split(attackType, ",")
	attackTypeCals := make([]interface{}, len(attackTypeArry))

	logTypeArry := strings.Split(logType, ",")
	logTypeCals := make([]interface{}, len(logTypeArry))

	serverNameArry := strings.Split(serverName, ",")
	serverNameCals := make([]interface{}, len(serverNameArry))

	clientIpArry := strings.Split(clientIp, ",")
	clientIpCals := make([]interface{}, len(clientIpArry))

	query := elastic.NewBoolQuery()
	query = query.Must(elastic.NewRangeQuery("hTime").Gte(startTime).Lte(endTime))
	//var titleArry = make([]string, 0)

	if appName != "" {
		for i, v := range strings.Split(appName, ",") {
			appNameCals[i] = v
		}
		query = query.Must(elastic.NewTermsQuery("appName.keyword", appNameCals...))
	}

	if attackType != "" {
		for i, v := range strings.Split(attackType, ",") {
			attackTypeCals[i] = v
		}
		query = query.Must(elastic.NewTermsQuery("attackType.keyword", attackTypeCals...))
	}

	if logType != "" {
		for i, v := range strings.Split(logType, ",") {
			logTypeCals[i] = v
		}
		query = query.Must(elastic.NewTermsQuery("logType.keyword", logTypeCals...))
	}

	if serverName != "" {
		for i, v := range strings.Split(serverName, ",") {
			serverNameCals[i] = v
		}
		query = query.Must(elastic.NewTermsQuery("serverName.keyword", serverNameCals...))
	}
	if clientIp != "" {
		for i, v := range strings.Split(clientIp, ",") {
			clientIpCals[i] = v
		}
		query = query.Must(elastic.NewTermsQuery("clientIp.keyword", clientIpCals...))
	}

	loc, _ := time.LoadLocation("Local") //重要：获取时区
	tmsT, _ := time.ParseInLocation("2006-01-02T15:04:05", startTime, loc)
	tmeT, _ := time.ParseInLocation("2006-01-02T15:04:05", endTime, loc)

	sTmp := tmsT.Unix() * 1000
	eTmp := tmeT.Unix() * 1000
	//log.Printf("st:%d,et:%d", sTmp, eTmp)
	indexstr := common.GetIndex("xwaf", sTmp, eTmp)

	queryResult := common.Esclient.Search().Index(indexstr...).Query(query).Size(0)
	//esearch := queryResult.Aggregation("warncount", elastic.NewDateHistogramAggregation().Field("hTime").Interval(intv).Format(dfmat).TimeZone("+08:00").
	//	SubAggregation(searchtype, elastic.NewTermsAggregation().Field(searchtype+".keyword").Size(50)))

	esearch := queryResult.Aggregation("serverNamecount", elastic.NewTermsAggregation().Field("serverName.keyword").Size(7).
		SubAggregation(searchtype, elastic.NewTermsAggregation().Field(searchtype+".keyword").Size(50)))

	ctx := context.Background()
	eresult, err1 := esearch.Do(ctx)
	if err1 != nil {
		panic(err1)
	}

	//var aggMap = make(map[string]int64)
	//totalhit := eresult.Hits.TotalHits

	//var count int64
	//var total float64

	var titleArry []string
	var nameArry = []string{"入侵防护", "防刷限流", "黑白名单"}
	var TmpMapArry = make(map[string][]int64)
	if agg, found := eresult.Aggregations.Terms("serverNamecount"); found {
		tmslength := len(agg.Buckets)
		TmpMapArry["入侵防护"] = make([]int64, tmslength)
		TmpMapArry["防刷限流"] = make([]int64, tmslength)
		TmpMapArry["黑白名单"] = make([]int64, tmslength)
		for ii, bucket := range agg.Buckets {
			titleArry = append(titleArry, bucket.Key.(string))
			aggSub, _ := bucket.Terms(searchtype)
			for _, subbucket := range aggSub.Buckets {
				var tt = subbucket.Key.(string)
				if tt == "waf" {
					tt = "入侵防护"
				}
				if tt == "reqlimit" {
					tt = "防刷限流"
				}
				if tt == "bwlist" {
					tt = "黑白名单"
				}
				TmpMapArry[tt][ii] = subbucket.DocCount
				fmt.Printf("key:%s,subkey:%s,subvalue:%d\n", bucket.Key.(string), subbucket.Key.(string), subbucket.DocCount)
			}
			fmt.Printf("key:%s,value:%d\n", bucket.Key.(string), bucket.DocCount)
		}
	}

	var bbb = make([]BarV2Item, 0)
	for kk, vv := range TmpMapArry {
		bbb = append(bbb, *&BarV2Item{kk, "bar", kk, vv}) //etype为bar[柱形]还是line[曲线],stack为total时为堆叠柱子，否则为独立的柱子
	}

	sMain := &BarV2Main{
		Code:     0,
		Title:    titleArry,
		Name:     nameArry,
		Subvalue: bbb,
	}

	this.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Origin", "*")
	this.Ctx.ResponseWriter.Header().Set("Content-Type", "application/json;charset=utf-8")

	jsonStr, jerr := json.Marshal(sMain)
	if jerr != nil {
		log.Println("ERROR: simpledetail json.Marshal error")
		//panic(jerr)
	}
	this.Ctx.WriteString(string(jsonStr))
}

type MapMain struct {
	Code  int64     `json:"code"`
	Msg   string    `json:"msg"`
	Count float64   `json:"count"`
	Max   float64   `json:"max"`
	Data  []MapItem `json:"data"`
}

type MapItem struct {
	Name  string  `json:"name"`
	Value float64 `json:"value"`
}

func (this *MetricController) ChinaMap() {
	//r.ParseForm()
	appName := this.GetString("appname")
	startTime := this.GetString("starttime")
	endTime := this.GetString("endtime")
	area := this.GetString("area")
	listenPort, _ := beego.AppConfig.String("httpport")
	//listenPort := strings.Trim(common.ConfMap["listen"].String(), "0.0.0.0")
	resp, err := http.Get("http://127.0.0.1" + listenPort + "/metric/v2/dist?key=clientIp&area=" + area + "&appName=" + appName + "&starttime=" + startTime + "&endtime=" + endTime)
	if err != nil {
		log.Printf("[ERROR] GroupContribute RequestFail:%s\n", err)
		return
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Printf("[ERROR] GroupIpContribute GetDistFail:%s\n", err)
	}
	var CityMap = make(map[string]float64)
	var count float64
	CityArry := gjson.ParseBytes(body).Get("data").Array()
	for _, vv := range CityArry {
		count += vv.Get("value").Float()
		if vc, ok := CityMap[vv.Get("remarks").String()]; ok {
			CityMap[vv.Get("remarks").String()] = vv.Get("value").Float() + vc
		} else {
			CityMap[vv.Get("remarks").String()] = vv.Get("value").Float()
		}
	}
	var maxvv float64
	var ItemArry = make([]MapItem, 0)
	for km, vm := range CityMap {
		dItems := &MapItem{
			Name:  km,
			Value: vm,
		}
		if vm > maxvv {
			maxvv = vm
		}
		ItemArry = append(ItemArry, *dItems)
	}
	sMain := &MapMain{
		Code:  0,
		Msg:   "success",
		Count: count,
		Max:   maxvv,
		Data:  ItemArry,
	}

	this.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Origin", "*")
	this.Ctx.ResponseWriter.Header().Set("Content-Type", "application/json;charset=utf-8")

	jsonStr, jerr := json.Marshal(sMain)
	if jerr != nil {
		log.Println("ERROR: simpledetail json.Marshal error")
	}
	this.Ctx.WriteString(string(jsonStr))
}

///metric/v1/dumplog日志查询
func (this *MetricController) DumpLog() {
	var appName, attackType, logType, serverName, clientIp, reqUrl, userAgent, startTime, endTime string
	appName = this.GetString("appname")

	key := this.GetString("key")
	page := this.GetString("page")
	limit := this.GetString("limit")

	if key == "" {
		key = "appName,serverName,serverIp,logType,clientIp,reqUrl,attackType,blockInfo,userAgent,hTime"
	}

	if this.Ctx.Request.Method == "POST" {
		gp := gjson.ParseBytes(this.Ctx.Input.RequestBody)
		if appName == "" {
			appName = gp.Get("appname").String()
		}
		attackType = gp.Get("attackType").String()
		logType = gp.Get("logType").String()
		serverName = gp.Get("serverName").String()
		clientIp = gp.Get("clientIp").String()
		reqUrl = gp.Get("reqUrl").String()
		userAgent = gp.Get("userAgent").String()
		startTime = gp.Get("starttime").String()
		endTime = gp.Get("endtime").String()

		page = gp.Get("page").String()
		limit = gp.Get("limit").String()

	}

	if this.Ctx.Request.Method == "GET" {
		attackType = this.GetString("attackType")
		logType = this.GetString("logType")
		serverName = this.GetString("serverName")
		clientIp = this.GetString("clientIp")
		reqUrl = this.GetString("reqUrl")
		userAgent = this.GetString("userAgent")
		startTime = this.GetString("starttime")
		endTime = this.GetString("endtime")
	}

	//paged, _ := strconv.ParseInt(page, 10, 64)
	paged, _ := strconv.Atoi(page)
	//limitd, err := strconv.ParseInt(limit, 10, 64)
	limitd, err := strconv.Atoi(limit)
	if err != nil {
		limitd = 200
	}
	//startpage := paged*limitd - limitd - paged
	startpage := paged*limitd - limitd
	if startpage < 0 {
		startpage = 0
	}
	if limitd == 0 {
		limitd = 200
	}

	if endTime == "" {
		endTime = time.Now().Format("2006-01-02T15:04:05")
	}
	if startTime == "" {
		//startTime = time.Now().Add(-1 * time.Hour).Format("2006-01-02T15:04:05")
		startTime = time.Now().Add(-20 * time.Minute).Format("2006-01-02T15:04:05")
	}

	var keyarry = []string{}
	if key == "" {
		keyarry = append(keyarry, "ip")
	} else {
		for _, vv := range strings.Split(key, ",") {
			if vv != "" {
				keyarry = append(keyarry, vv)
			}
		}
	}

	// tsize := this.GetString("size")
	// var totalsize int
	// var err error
	// if tsize == "" {
	// 	totalsize = 1000
	// } else {
	// 	totalsize, err = strconv.Atoi(tsize)
	// 	if err != nil {
	// 		log.Printf("ERROR: dumpip size strconv.Atoi error:%s\n", err)
	// 		//panic(err)
	// 	}
	// }

	appNameArry := strings.Split(appName, ",")
	appNameCals := make([]interface{}, len(appNameArry))

	attackTypeArry := strings.Split(attackType, ",")
	attackTypeCals := make([]interface{}, len(attackTypeArry))

	logTypeArry := strings.Split(logType, ",")
	logTypeCals := make([]interface{}, len(logTypeArry))

	serverNameArry := strings.Split(serverName, ",")
	serverNameCals := make([]interface{}, len(serverNameArry))

	//clientIpArry := strings.Split(clientIp, ",")
	//clientIpCals := make([]interface{}, len(clientIpArry))

	query := elastic.NewBoolQuery()
	query = query.Must(elastic.NewRangeQuery("hTime").Gte(startTime).Lte(endTime))
	//var titleArry = make([]string, 0)

	if appName != "" {
		for i, v := range strings.Split(appName, ",") {
			appNameCals[i] = v
		}
		query = query.Must(elastic.NewTermsQuery("appName.keyword", appNameCals...))
	}

	if attackType != "" {
		for i, v := range strings.Split(attackType, ",") {
			attackTypeCals[i] = v
		}
		query = query.Must(elastic.NewTermsQuery("attackType.keyword", attackTypeCals...))
	}

	if logType != "" {
		for i, v := range strings.Split(logType, ",") {
			logTypeCals[i] = v
		}
		query = query.Must(elastic.NewTermsQuery("logType.keyword", logTypeCals...))
	}

	if serverName != "" {
		for i, v := range strings.Split(serverName, ",") {
			serverNameCals[i] = v
		}
		query = query.Must(elastic.NewTermsQuery("serverName.keyword", serverNameCals...))
		//query = query.Must(elastic.NewMatchQuery("serverName.keyword", serverNameCals...))
	}

	if clientIp != "" {
		query = query.Must(elastic.NewMatchQuery("clientIp.keyword", clientIp))
	}

	if reqUrl != "" {
		query = query.Must(elastic.NewMatchQuery("reqUrl.keyword", reqUrl))
	}

	if userAgent != "" {
		query = query.Must(elastic.NewMatchQuery("userAgent.keyword", userAgent))
	}

	// if region != "" {
	// 	query = query.Must(elastic.NewMatchQuery("region.keyword", region))
	// }
	// if city != "" {
	// 	query = query.Must(elastic.NewMatchQuery("city.keyword", city))
	// }
	// if isp != "" {
	// 	query = query.Must(elastic.NewMatchQuery("isp.keyword", isp))
	// }

	loc, _ := time.LoadLocation("Local") //重要：获取时区
	tmsT, _ := time.ParseInLocation("2006-01-02T15:04:05", startTime, loc)
	tmeT, _ := time.ParseInLocation("2006-01-02T15:04:05", endTime, loc)

	sTmp := tmsT.Unix() * 1000
	eTmp := tmeT.Unix() * 1000
	//log.Printf("st:%d,et:%d", sTmp, eTmp)
	indexstr := common.GetIndex("xwaf", sTmp, eTmp)

	ctx := context.Background()
	search := common.Esclient.Search().Index(indexstr...).Query(query).From(startpage).Size(limitd).Sort("hTime", false)
	esearch := search.FetchSourceContext(elastic.NewFetchSourceContext(true).Include(keyarry...))

	var code int
	var msg = "success"
	var count = 5000
	eresult, err1 := esearch.Do(ctx)
	if err1 != nil {
		log.Printf("[ERROR] search.Do Error:%s\n", err1)
		code = 1
		count = 0
		msg = "search.DoFail"
	}
	//var ly LineArry = make([]LineItem, 0, len(result))
	var strarry = []string{}
	result := eresult.Hits.Hits
	for _, b := range result {
		cc, _ := b.Source.MarshalJSON()
		//if err := json.Unmarshal(cc, &ck); err != nil {
		//	fmt.Println(err)
		//}
		//fmt.Println(string(cc))
		strarry = append(strarry, string(cc))
		//ly = append(ly, *&LineItem{ck.ChkTime, ck.RequestTime})
	}

	this.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Origin", "*")
	this.Ctx.ResponseWriter.Header().Set("Content-Type", "application/json;charset=utf-8")
	//jsonStr, err := json.Marshal(strarry)
	//if err != nil {
	//	fmt.Println(err)
	//}
	//count = len(strarry)
	tmpstr := strings.Replace(fmt.Sprint(strarry), " ", ",", -1)
	tmpstr = strings.Replace(tmpstr, "script", "_script", -1)
	tmpstr = strings.Replace(tmpstr, "<", "-", -1)
	respbody := fmt.Sprintf(`{"code":%d,"msg":"%s","count":%d,"data":%s}`, code, msg, count, tmpstr)
	this.Ctx.WriteString(respbody)
}

func (this *MetricController) GetIp() {
	startTime := time.Now().UnixNano()
	var ips string
	ips = this.GetString("ip")
	if ips == "" {
		if xff := this.Ctx.Input.Header("X-Forwarded-For"); xff != "" {
			xffarry := strings.Split(xff, ",")
			for i := 0; i < len(xffarry); i++ {
				if !(strings.HasPrefix(xffarry[i], "192.168") || strings.HasPrefix(xffarry[i], "127.0.0") || strings.HasPrefix(xffarry[i], "10.")) {
					ips = xffarry[i]
					break
				}
			}
			if ips == "" {
				ips = strings.Split(xff, ",")[0]
			}
		} else {
			ips = strings.Split(this.Ctx.Request.RemoteAddr, ":")[0]
		}
	}
	ipstr, err := ip2regionv2.Iprg.SearchByStr(strings.TrimSpace(ips))
	endTime := time.Now().UnixNano()

	this.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Origin", "*")
	this.Ctx.ResponseWriter.Header().Set("Content-Type", "application/json;charset=utf-8")

	//log.Printf("getip spent:%.1f ms\n", float64(endTime-startTime)/1000000)
	if err != nil {
		log.Printf("SearchIp Fail:%s\n", err)
		this.Ctx.WriteString("{\"msg\":\"fail\"}")
		return
	}
	//log.Printf("TEST:%s", ipstr)
	ipinfo := ip2regionv2.IpStrToJson(ipstr)
	//jsonstr := fmt.Sprintf(`{"ip":"%s","region":"%s","city":"%s","isp":"%s"}`, ips, strings.Trim(ipinfo.Province, "省"), strings.Trim(ipinfo.City, "市"), ipinfo.ISP)
	jsonstr := fmt.Sprintf(`{"ip":"%s","country":"%s","region":"%s","city":"%s","isp":"%s"}`, strings.TrimSpace(ips), ipinfo.Country, ipinfo.Province, ipinfo.City, ipinfo.ISP)
	log.Printf("SearchIp Success spent:%.1f ms,result:%s\n", float64(endTime-startTime)/1000000, jsonstr)
	this.Ctx.WriteString(jsonstr)
}
